package pl.edu.pw.ee.buildcity.services;

import org.apache.log4j.Logger;
import org.apache.maven.shared.invoker.*;
import pl.edu.pw.ee.buildcity.commons.exceptions.BuildCityRuntimeException;
import pl.edu.pw.ee.buildcity.domain.BuildStatus;
import pl.edu.pw.ee.buildcity.logs.LogsManager;
import pl.edu.pw.ee.buildcity.services.api.BuilderService;

import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.apache.commons.lang.StringUtils.isBlank;

/**
 * @author mgrzechocinski
 * @since 2009-10-18
 */
public class MavenBuilderService implements BuilderService {

	private static final Logger log = Logger.getLogger(MavenBuilderService.class);
	
	private static final int SUCCEEDED_EXIT_CODE = 0;
	private static final String POM_FILENAME = "pom.xml";
	
	@Resource(name = "logsManager")
	private LogsManager<MavenLogsHandler> logsManager;

	@Override
	public BuildStatus build(File workingCopy, String buildCommand) {

		Invoker invoker = new DefaultInvoker();

		try {
			performBuild(workingCopy, buildCommand, invoker);
			return BuildStatus.SUCCEEDED;

		} catch (BuildCityRuntimeException e) {
			log.warn(e.getMessage());
		} catch (Exception e) {
			log.error("Error while invoking Maven build: " + e.getMessage(), e);
		}
		return BuildStatus.FAILED;
	}

	private void performBuild(File workingCopy, String buildCommand, Invoker invoker) throws MavenInvocationException {
		InvocationRequest request = createInvocationRequest(workingCopy, buildCommand);

		log.info("Performing 'mvn " + request.getGoals() + "' on " + request.getPomFile());
		int exitCode = invoker.execute(request).getExitCode();

		// see: http://maven.apache.org/shared/maven-invoker/usage.html
		if (exitCode != SUCCEEDED_EXIT_CODE) {
			throw new BuildCityRuntimeException("Build failed! Exit code is " + exitCode);
		}
	}

	private InvocationRequest createInvocationRequest(File workingCopy, String buildCommand) {
		InvocationRequest request = new DefaultInvocationRequest();
		request.setPomFile(getWorkingCopyPomFile(workingCopy));
		request.setInteractive(false);
		request.setShowErrors(false);
		request.setGoals(createListOfGoals(buildCommand));
		configureOutputHandler(workingCopy, request);
		return request;
	}

	private void configureOutputHandler(File workingCopy, InvocationRequest request) {
		MavenLogsHandler outputHandler = new MavenLogsHandler();
		logsManager.registerLogHandler(workingCopy, outputHandler);
		request.setOutputHandler(outputHandler);
	}

	private List<String> createListOfGoals(String buildCommand) {
		if (isBlank(buildCommand)) {
			log.warn("Given build command is empty - no goals were specified...");
			return Collections.emptyList();
		}
		String[] goals = buildCommand.split("\\s");
		return Arrays.asList(goals);
	}

	private File getWorkingCopyPomFile(File workingCopy) {
		StringBuilder workingCopyPath = new StringBuilder(workingCopy.getAbsolutePath());
		workingCopyPath.append(File.separator);
		workingCopyPath.append(POM_FILENAME);
		return new File(workingCopyPath.toString());
	}
}